use crate::http_api::message::SatoriMessageData;
use crate::model::satori::{SatoriChannel, SatoriChannelType, SatoriMessage};
use crate::ws::{AppState, SenderData};
use axum::extract::ws::{Message, WebSocket};
use futures_util::stream::SplitStream;
use futures_util::StreamExt;
use serde_json::Value;
use uuid::Uuid;
use void_log::{log_error, log_msg};
use crate::model::sys_user::SysUser;
use crate::satori_api;

impl AppState {
    async fn message_text(&self, text: &str, username: &str) {
        let msg = match satori_api::json_to_self::<Value>(text) {
            Ok(data) => { data }
            Err(e) => {
                log_error!("Json Error: {}", e);
                return;
            }
        };
        log_msg!("接收消息: {:?}", &msg);

        // 发送消息
        match msg.method.as_str() {
            "message.create" => {
                if let Ok(msg_data) = serde_json::from_value::<SatoriMessageData>(msg.data) {
                    self.message_create(msg_data, username).await
                };
            }
            _ => {}
        }
    }

    pub async fn receive_task(self, mut receiver: SplitStream<WebSocket>, userid: Uuid) {
        let user = SysUser::select(&self.pool, &userid).await.unwrap();
        let username = format!("{}#{}", user.account.unwrap(), user.code.unwrap());
        // 上线广播
        self.system_msg(format!("用户 '{}' 已上线", &username)).await;

        // 消息待命
        while let Some(Ok(message)) = receiver.next().await {
            match message {
                // 文本消息
                Message::Text(text) => {
                    let _ = &self.message_text(&text, &username).await;
                }
                // 连接关闭
                Message::Close(Some(msg)) => {
                    log_msg!("Close: {:?}", &msg);
                    break;
                }
                // 其他消息
                _ => { continue }
            }
        }

        // 下线广播
        self.system_msg(format!("用户 '{}' 已下线", &username)).await;

        // 下线清除登录状态
        self.clients.remove(&userid);
    }

    async fn system_msg(&self, content: String) {
        let satori_message_up = SatoriMessage {
            id: "00000".to_string(),
            content,
            channel: Some(SatoriChannel {
                id: "all".to_string(),
                r#type: SatoriChannelType::TEXT,
                ..Default::default()
            }),
            ..Default::default()
        };

        let sender_data = SenderData {
            to_user: "all".to_string(),
            satori_message: satori_message_up,
        };
        let _ = &self.sender_tx.send(sender_data).await.unwrap();
    }
}